package com.tarena.lbs.basic.web.repository;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.basic.web.mapper.StoreMapper;
import com.tarena.lbs.pojo.basic.entity.StoreSearchEntity;
import com.tarena.lbs.pojo.basic.param.UserLocationParam;
import com.tarena.lbs.pojo.basic.po.StorePO;
import com.tarena.lbs.pojo.basic.query.AreaStoreQuery;
import com.tarena.lbs.pojo.basic.query.StoreQuery;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Repository
@Slf4j
public class StoreRepository {
    @Autowired
    private StoreMapper storeMapper;
    @Autowired
    private StoreESRepository storeESRepository;
    @Autowired
    private RestHighLevelClient client;
    public PageInfo<StorePO> getStores(StoreQuery query) {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        //拼接查询的条件 只判断businessId
        if (query.getBusinessId()!=null){
            //商家账号查询 查询店铺必须属于该商家
            queryWrapper.eq("business_id", query.getBusinessId());
        }
        //开启PageHelper
        PageHelper.startPage(query.getPageNo(), query.getPageSize());
        List<StorePO> pos = storeMapper.selectList(queryWrapper);
        return new PageInfo<>(pos);
    }

    public void save(StorePO poParam) {
        //新增数据到mysql
        storeMapper.insert(poParam);
        // 新增到ES(将地理位置存储到数据库)
        //1. 配置ES项目环境 使用repository接口 定义entity文档对象
        //2. 手写底层API代码 组织storeEntity新增-RestHighLevelClient
        StoreSearchEntity entity=new StoreSearchEntity();
        //新增自增的店铺id
        //前端传递的维度经度度的地理位置
        //店铺名称
        BeanUtils.copyProperties(poParam,entity);
        entity.setLocation(poParam.getStoreLatitude()+","+poParam.getStoreLongitude());//将维度lat和精度lon用逗号拼接

        storeESRepository.save(entity);

    }

    public List<StorePO> getAreaStores(AreaStoreQuery query, Integer businessId) {
        //select * from lbs_store where business_id=#{businessId} and (provinc in city in area in )
        QueryWrapper<StorePO> queryWrapper=new QueryWrapper();
        queryWrapper.eq("business_id",businessId).
                and(
                        wq->wq.in("province_id",query.getCityIdList()).
                                or().in("city_id",query.getCityIdList()).
                                or().in("area_id",query.getCityIdList()));//business_id=#{businessId}
        return storeMapper.selectList(queryWrapper);// select where business_id and province in or city or area
    }


    public List<StorePO> getStoresByBizId(Integer id) {
        //select * from lbs_store where business_id=#{id}
        QueryWrapper<StorePO> queryWrapper=new QueryWrapper();
        queryWrapper.eq("business_id",id);
        return storeMapper.selectList(queryWrapper);
    }

    public List<StoreSearchEntity> getNearestStores(UserLocationParam param) {
        List<StoreSearchEntity> stores=null;
        //搜索查询es中lbs_store索引 分页0,5 排序 location 升序
        SearchRequest searchRequest=new SearchRequest("lbs_store");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        //1.构造查询请求
        //2.请求封装参数
        sourceBuilder.from(0);
        sourceBuilder.size(5);
        //location是字符串text类型,比较字符串 locaiton是geo_point 默认距离排序
        //sourceBuilder.sort("location", SortOrder.ASC);//默认计算方法 如果是数字 大小 如果是字符串 对比
        //如果geo_point做距离排序 api 提供一个排序的规则 基于中心点 距离distance
        GeoPoint center=new GeoPoint(Double.valueOf(param.getLatitude()),Double.valueOf(param.getLongitude()));
        GeoDistanceSortBuilder sortBuilder=new GeoDistanceSortBuilder("location",center);
        sortBuilder.order(SortOrder.DESC);//越近 越靠前
        sortBuilder.unit(DistanceUnit.METERS);
        sourceBuilder.sort(sortBuilder);
        GeoDistanceQueryBuilder query = QueryBuilders.geoDistanceQuery("location").point(center).distance("50", DistanceUnit.KILOMETERS);
        sourceBuilder.query(query);
        searchRequest.source(sourceBuilder);
        //3.发起请求
        try {
            SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
            SearchHit[] hits = response.getHits().getHits();
            if (hits!=null&&hits.length>0){
                stores= Arrays.stream(hits).map(hit->{
                    String sourceAsString = hit.getSourceAsString();//文档json
                    return JSON.parseObject(sourceAsString,StoreSearchEntity.class);
                }).collect(Collectors.toList());
            }
        } catch (IOException e) {
            log.error("查询es失败",e);
        }
        //4.封装结果
        return stores;
    }
}
